home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-09-17 | 36.4 KB | 1,209 lines | [TEXT/MPS ] |
- //========================================================================================
- //
- // File: FWLnkMgr.cpp
- // Release Version: $ ODF 2 $
- //
- // Copyright: (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
- //
- //========================================================================================
-
- #include "FWFrameW.hpp"
-
- #ifndef FWLNKMGR_H
- #include "FWLnkMgr.h"
- #endif
-
- // ----- Framework Includes -----
-
- #ifndef FWPART_H
- #include "FWPart.h"
- #endif
-
- #ifndef FWPRESEN_H
- #include "FWPresen.h"
- #endif
-
- #ifndef FWLNKITE_H
- #include "FWLnkIte.h"
- #endif
-
- #ifndef FWUTIL_H
- #include "FWUtil.h"
- #endif
-
- #ifndef FWCLNINF_H
- #include "FWClnInf.h"
- #endif
-
- #ifndef FWLNKCMD_H
- #include "FWLnkCmd.h"
- #endif
-
- #ifndef FWSESION_H
- #include "FWSesion.h"
- #endif
-
- #ifndef FWLINK_K
- #include "FWLink.k"
- #endif
-
- // ----- Foundation Includes -----
-
- #ifndef FWPRIDEB_H
- #include "FWPriDeb.h"
- #endif
-
- #ifndef FWMEMMGR_H
- #include "FWMemMgr.h"
- #endif
-
- #ifndef FWBARRAY_H
- #include "FWBArray.h"
- #endif
-
- // ----- OS Includes -----
-
- #ifndef FWTIME_H
- #include "FWTime.h"
- #endif
-
- #ifndef FWSUUTIL_H
- #include "FWSUUtil.h"
- #endif
-
- #ifndef FWCFMRES_H
- #include "FWCFMRes.h"
- #endif
-
- // For FW_kUndoPasteAsMsg
- #ifndef SLODFSTR_K
- #include "SLODFStr.k"
- #endif
-
- // For FW_PrivLoadODFString
- #ifndef SLODFSTR_H
- #include "SLODFStr.h"
- #endif
-
- // ----- OpenDoc Includes -----
-
- #ifndef SOM_Module_OpenDoc_StdProps_defined
- #include <StdProps.xh>
- #endif
-
- #ifndef SOM_Module_OpenDoc_StdTypes_defined
- #include <StdTypes.xh>
- #endif
-
- #ifndef SOM_ODStorageUnit_xh
- #include <StorageU.xh>
- #endif
-
- #ifndef SOM_ODDraft_xh
- #include <Draft.xh>
- #endif
-
- #ifndef SOM_ODClipboard_xh
- #include <Clipbd.xh>
- #endif
-
- #ifndef SOM_ODLink_xh
- #include <Link.xh>
- #endif
-
- #ifndef SOM_ODLinkSpec_xh
- #include <LinkSpec.xh>
- #endif
-
- #ifndef SOM_ODLinkSource_xh
- #include <LinkSrc.xh>
- #endif
-
- #if defined(FW_BUILD_MAC) && !defined(__DIALOGS__)
- #include <Dialogs.h>
- #endif
-
- //========================================================================================
- // Runtime information
- //========================================================================================
-
- #ifdef FW_BUILD_MAC
- #pragma segment odflinking
- #endif
-
- //========================================================================================
- // class FW_CLinkManager
- //========================================================================================
-
- FW_DEFINE_AUTO(FW_CLinkManager)
-
- //---------------------------------------------------------------------------------------
- // FW_CLinkManager constructor
- //---------------------------------------------------------------------------------------
-
- FW_CLinkManager::FW_CLinkManager(Environment* ev, FW_CPart* thePart) :
- fPart(thePart),
- fPendingClipboardLink(NULL),
- fPendingDropLink(NULL),
- fSourceLinkList(NULL),
- fDestLinkList(NULL)
- {
- FW_UNUSED(ev);
- FW_END_CONSTRUCTOR
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CLinkManager destructor
- //---------------------------------------------------------------------------------------
-
- FW_CLinkManager::~FW_CLinkManager()
- {
- FW_START_DESTRUCTOR
-
- delete fDestLinkList;
- fDestLinkList = NULL;
-
- delete fSourceLinkList;
- fSourceLinkList = NULL;
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CLinkManager::RemoveAllLinks
- //---------------------------------------------------------------------------------------
-
- void FW_CLinkManager::RemoveAllLinks(Environment* ev)
- {
- FW_UNUSED(ev);
- // ----- Delete source links -----
- if (fSourceLinkList)
- {
- FW_CLinkSource* link;
- while ((link = fSourceLinkList->First()) != NULL)
- {
- fSourceLinkList->Remove(link);
- delete link;
- }
- }
-
- // ----- Delete destination links -----
- if (fDestLinkList)
- {
- FW_CLinkDestination* link;
- while ((link = fDestLinkList->First()) != NULL)
- {
- fDestLinkList->Remove(link);
- delete link;
- }
- }
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CLinkManager::AddToSourceLinkList
- //---------------------------------------------------------------------------------------
-
- void FW_CLinkManager::AddToSourceLinkList(Environment* ev, FW_CLinkSource* linkSource)
- {
- FW_UNUSED(ev);
- if (fSourceLinkList == NULL)
- fSourceLinkList = FW_NEW(FW_TOrderedCollection<FW_CLinkSource>, ());
- else if (fSourceLinkList->Contains(linkSource))
- return;
-
- fSourceLinkList->AddLast(linkSource);
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CLinkManager::AddToDestLinkList
- //---------------------------------------------------------------------------------------
-
- void FW_CLinkManager::AddToDestLinkList(Environment* ev, FW_CLinkDestination* linkDest)
- {
- FW_UNUSED(ev);
- if (fDestLinkList == NULL)
- fDestLinkList = FW_NEW(FW_TOrderedCollection<FW_CLinkDestination>, ());
- else if (fDestLinkList->Contains(linkDest))
- return;
-
- fDestLinkList->AddLast(linkDest);
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CLinkManager::BreakSourceLink
- //---------------------------------------------------------------------------------------
- void FW_CLinkManager::BreakSourceLink(Environment* ev, FW_CLinkSource* linkSource)
- {
- linkSource->BreakLink(ev);
- this->RemoveFromSourceLinkList(ev, linkSource);
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CLinkManager::BreakDestinationLink
- //---------------------------------------------------------------------------------------
- void FW_CLinkManager::BreakDestinationLink(Environment* ev, FW_CLinkDestination* linkDest)
- {
- linkDest->BreakLink(ev);
- this->RemoveFromDestLinkList(ev, linkDest);
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CLinkManager::CountSourceLinks
- //---------------------------------------------------------------------------------------
-
- unsigned long FW_CLinkManager::CountSourceLinks(Environment* ev) const
- {
- FW_UNUSED(ev);
- if (fSourceLinkList)
- return fSourceLinkList->Count();
-
- return 0;
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CLinkManager::CountDestinationLinks
- //---------------------------------------------------------------------------------------
-
- unsigned long FW_CLinkManager::CountDestinationLinks(Environment* ev) const
- {
- FW_UNUSED(ev);
- if (fDestLinkList)
- return fDestLinkList->Count();
-
- return 0;
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CLinkManager::CreateLink
- //---------------------------------------------------------------------------------------
-
- ODLinkSource* FW_CLinkManager::CreateLink(Environment* ev, ODByteArray* data)
- {
- ODLinkSource* odLinkSource = NULL;
- ODUpdateID updateID = *((ODUpdateID*)(data->_buffer));
-
- // The link spec is either on the clipboard or saved from a Drag&Drop operation.
- // Determine which one to use by checking the ids
- FW_Boolean linkSpecOnClipboard = true;
-
- // --- Check the clipboard link spec first, since it's the most likely candidate ---
- FW_CLinkSource* pendingLink = this->GetPendingClipboardLink(ev);
- if (pendingLink && (pendingLink->GetPendingID(ev) == updateID))
- {
- // Get the link if it already exists
- odLinkSource = pendingLink->GetODLinkSource(ev);
- }
- else // check for a Drag&Drop link spec
- {
- pendingLink = this->GetPendingDropLink(ev);
- FW_ASSERT(pendingLink != NULL);
- FW_ASSERT(pendingLink->GetPendingID(ev) == updateID);
- linkSpecOnClipboard = false;
-
- // The Drag&Drop link spec is only good for creating one link
- this->PrivSetPendingDropLink(ev, NULL);
- }
-
- if (odLinkSource == NULL) // link does not yet exist
- {
- FW_CPrivCreateLinkSourceCommand* cmd = pendingLink->PrivGetPendingCommand(ev);
- FW_Boolean cmdExecuted = true;
-
- FW_TRY
- {
- if (!cmd)
- {
- FW_CFrame* frame = fPart->GetLastActiveFrame(ev); /* ??? */
- cmd = FW_NEW(FW_CPrivCreateLinkSourceCommand, (ev, frame, this, pendingLink));
- cmdExecuted = cmd->Execute(ev);
- }
- else
- {
- cmd->SetLinkSource(ev, pendingLink);
- }
-
- if (cmdExecuted)
- {
- odLinkSource = cmd->GetODLinkSource(ev);
- // Don't DeletePendingClipboardLink, because more links may be created from it
- }
- // else cmd has been deleted
- }
- FW_CATCH_BEGIN
- FW_CATCH_EVERYTHING()
- {
- // $$$$$ [MH] I don't think that this should be trapped!
- // Perhaps returning a null ODLinkSource is sufficient, but
- // the failure must propagate to the intended destination.
-
- // don't re-throw; odLinkSource remains NULL
- }
- FW_CATCH_END
- }
- else
- {
- pendingLink->ContentUpdated(ev, kODUnknownUpdate, TRUE);
- odLinkSource->Acquire(ev);
- }
-
- return odLinkSource;
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CLinkManager::DeletePendingClipboardLink
- //---------------------------------------------------------------------------------------
-
- void FW_CLinkManager::DeletePendingClipboardLink(Environment* ev)
- {
- if (fPendingClipboardLink != NULL)
- {
- ODClipboard* clipboard = FW_CSession::GetClipboard(ev);
-
- if (fPendingClipboardLink->GetPendingID(ev) == clipboard->GetUpdateID(ev))
- {
- ODStorageUnit* clipboardSU = clipboard->GetContentStorageUnit(ev);
- if (clipboardSU->Exists(ev, kODPropLinkSpec, (ODValueType) NULL, 0) == TRUE)
- {
- clipboardSU->Focus(ev, kODPropLinkSpec, kODPosUndefined, (ODValueType) NULL, 0, kODPosUndefined);
- clipboardSU->Remove(ev);
- }
- }
-
- if (fPendingClipboardLink->IsPending(ev)) // CreateLink was never called
- delete fPendingClipboardLink;
-
- fPendingClipboardLink = NULL;
- }
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CLinkManager::DoChangeLinkStatus
- //---------------------------------------------------------------------------------------
-
- void FW_CLinkManager::DoChangeLinkStatus(Environment* ev, ODFrame* odFrame)
- {
- FW_UNUSED(ev);
- FW_UNUSED(odFrame);
- // Embedding parts should override to call ODFrame::ChangeLinkStatus for any
- // embedded frames that are involved in a link when a link is created, broken, moved, etc.
- // odFrame is the frame whose link status has changed.
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CLinkManager::DoUpdateLinks
- //---------------------------------------------------------------------------------------
-
- void FW_CLinkManager::DoUpdateLinks(Environment* ev,
- ODFrame* odEmbeddedFrame,
- ODUpdateID updateID)
- {
- // An embedded frame has changed. (Formerly named EmbeddedFrameUpdated)
- // If odEmbeddedFrame is involved in one of my link sources, update the link with new data.
-
- if (this->CountSourceLinks(ev) > 0)
- {
- FW_CLinkMgrLinkSourceIterator iter(this);
- for (FW_CLinkSource* link = iter.First(); iter.IsNotComplete(); link = iter.Next())
- {
- if (link->HasEmbeddedFrame(ev, odEmbeddedFrame))
- {
- link->ContentUpdated(ev, updateID, FALSE);
- break;
- }
- }
- }
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CLinkManager::EditInLinkAttempted
- //---------------------------------------------------------------------------------------
-
- FW_Boolean FW_CLinkManager::EditInLinkAttempted(Environment* ev, ODFrame* odFrame)
- {
- // --- Is there a link destination involving odFrame?
- FW_CLinkDestination* linkDest = NULL;
- FW_CFrame* frame = NULL;
- if (this->CountDestinationLinks(ev) > 0)
- {
- FW_CLinkMgrLinkDestIterator it(this);
- for (FW_CLinkDestination* link = it.First(); it.IsNotComplete(); link = it.Next())
- {
- frame = link->GetContainingFrame(ev, odFrame);
- if (frame != NULL)
- {
- linkDest = link;
- break;
- }
- }
- }
-
- if (linkDest == NULL) // can't find the link
- return false;
-
- EditInLinkAlert(ev, linkDest, frame);
- return true;
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CLinkManager::EditInLinkAlert
- //---------------------------------------------------------------------------------------
- FW_Boolean FW_CLinkManager::EditInLinkAlert(Environment* ev, FW_CLinkDestination* linkDest, FW_CFrame* frame)
- {
- // We need to be in front to show the dlg. If we're not
- // then the attempt to edit must be drop into a backround doc.
- // we can't come to the front during a drop (I've tried it, nothing
- // happens), so we'll just return false in that case. If we could defer putting the dlg
- // up, then we would come to the front after the drop completes, but that does no good
- // since we have to determine whether to accept the drop or not now.
-
- FW_ASSERT(frame);
-
- if (!frame->GetWindow(ev)->IsActive(ev))
- return false;
-
- // Present alert box to user with 3 choices: Find Source, Break Link, or Cancel
- // Return TRUE if user chooses to break the link so that she can edit
- short reply = PrivShowEditInLinkAlert(ev);
- if (reply == FW_kFindSourceButtonID)
- {
- this->PrivShowLinkSource(ev, linkDest);
- }
- else if (reply == FW_kBreakLinkButtonID)
- {
- FW_CBreakLinkCommand* cmd = FW_NEW(FW_CBreakLinkCommand, (ev, frame, linkDest, this));
- cmd->Execute(ev);
- }
- // else reply == FW_kCancelEditButtonID, so just return
-
- return (reply == FW_kBreakLinkButtonID);
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CLinkManager::ODtoFWLinkSource
- //---------------------------------------------------------------------------------------
-
- FW_CLinkSource* FW_CLinkManager::ODtoFWLinkSource(Environment* ev, ODLinkSource* odLinkSource) const
- {
- FW_TOrderedCollectionIterator<FW_CLinkSource> iter(fSourceLinkList);
- for (FW_CLinkSource* link = iter.First(); iter.IsNotComplete(); link = iter.Next())
- {
- if (odLinkSource->IsEqualTo(ev, link->GetODLinkSource(ev)))
- return link;
- }
- return NULL;
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CLinkManager::ODtoFWLink
- //---------------------------------------------------------------------------------------
-
- FW_CLinkDestination* FW_CLinkManager::ODtoFWLink(Environment* ev, ODLink* odLink) const
- {
- FW_TOrderedCollectionIterator<FW_CLinkDestination> iter(fDestLinkList);
- for (FW_CLinkDestination* link = iter.First(); iter.IsNotComplete(); link = iter.Next())
- {
- if (odLink->IsEqualTo(ev, link->GetODLink(ev)))
- return link;
- }
- return NULL;
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CLinkManager::RevealLink
- //---------------------------------------------------------------------------------------
-
- void FW_CLinkManager::RevealLink(Environment* ev, ODLinkSource* odLinkSource)
- {
- FW_CLinkSource* sourceLink = ODtoFWLinkSource(ev, odLinkSource);
- if (sourceLink == NULL) // can't find link
- return;
-
- // Choose a display frame for the source content
- FW_CFrame* frame = sourceLink->GetFrameToRevealLink(ev); // part-specific
- if (frame)
- {
- // ----- Activate the frame's window -----
- if (!frame->GetWindow(ev)->IsActive(ev))
- frame->GetWindow(ev)->Select(ev);
-
- // ----- Activate the frame -----
- if (!frame->HasSelectionFocus(ev))
- {
- frame->ActivateFrame(ev, NULL);
-
- // FW_CFrameFacetIterator iter(ev, frame); // find a facet
- // frame->ActivateFrame(ev, iter.First(ev));
- }
-
- // ----- Tell the link source to reveal its content -----
- sourceLink->RevealLinkSource(ev, frame);
- }
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CLinkManager::RemoveFromSourceLinkList
- //---------------------------------------------------------------------------------------
-
- void FW_CLinkManager::RemoveFromSourceLinkList(Environment* ev, FW_CLinkSource* linkSource)
- {
- if (fSourceLinkList)
- {
- fSourceLinkList->Remove(linkSource);
-
- if (linkSource == fPendingClipboardLink)
- this->DeletePendingClipboardLink(ev);
-
- if (fSourceLinkList->Count() == 0)
- {
- delete fSourceLinkList;
- fSourceLinkList = NULL;
- }
- }
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CLinkManager::RemoveFromDestLinkList
- //---------------------------------------------------------------------------------------
-
- void FW_CLinkManager::RemoveFromDestLinkList(Environment* ev, FW_CLinkDestination* linkDest)
- {
- FW_UNUSED(ev);
-
- if (fDestLinkList)
- {
- fDestLinkList->Remove(linkDest);
-
- if (fDestLinkList->Count() == 0)
- {
- delete fDestLinkList;
- fDestLinkList = NULL;
- }
- }
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CLinkManager::RestoreSourceLink
- //---------------------------------------------------------------------------------------
- void FW_CLinkManager::RestoreSourceLink(Environment* ev, FW_CLinkSource* linkSource)
- {
- this->AddToSourceLinkList(ev, linkSource);
- linkSource->RestoreLink(ev, fPart);
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CLinkManager::RestoreDestinationLink
- //---------------------------------------------------------------------------------------
- void FW_CLinkManager::RestoreDestinationLink(Environment* ev, FW_CLinkDestination* linkDest)
- {
- this->AddToDestLinkList(ev, linkDest);
- linkDest->RestoreLink(ev, fPart);
- linkDest->PrivEstablishLink(ev);
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CLinkManager::PasteWithLink
- //---------------------------------------------------------------------------------------
- FW_CLinkDestination* FW_CLinkManager::PasteWithLink(Environment* ev, ODStorageUnit* storageUnit,
- ODPasteAsResult& pasteAsResult,
- FW_CFrame* frame,
- FW_StorageKinds storageKind)
- {
- FW_CLinkDestination* linkDest = NULL;
- ODLinkSpec* linkSpec = NULL;
- ODLink* odLink = NULL;
- ODDraft* draft = fPart->GetDraft(ev);
- if (!storageUnit->Exists(ev, kODPropLinkSpec, (ODValueType)NULL, 0))
- return linkDest;
-
- FW_CPrivCreateLinkCommand* cmd = NULL;
- FW_VOLATILE(cmd);
- FW_VOLATILE(linkSpec);
- FW_VOLATILE(odLink);
-
- FW_TRY
- {
- linkSpec = draft->CreateLinkSpec(ev, NULL, NULL);
-
- storageUnit->Focus(ev, kODPropLinkSpec, kODPosUndefined, (ODValueType)NULL, 0, kODPosUndefined);
- linkSpec->ReadLinkSpec(ev, storageUnit);
-
- // ---- Write a transaction to the Undo history ----
- cmd = FW_NEW(FW_CPrivCreateLinkCommand, (ev, frame, this, storageKind == FW_kClipboardStorage));
- cmd->Execute(ev);
-
- // ---- Establish the Link ----
- odLink = draft->AcquireLink(ev, (ODStorageUnitID)0, linkSpec); // use linkSpec to retrieve the link
-
- if (odLink)
- {
- // --- Embed or incorporate the link ---
- linkDest = this->PrivMakeLink(ev, odLink, pasteAsResult, frame->GetPresentation(ev));
- cmd->SetLink(ev, linkDest);
- odLink->Release(ev); // to balance AcquireLink
- }
- }
- FW_CATCH_BEGIN
- FW_CATCH_EVERYTHING()
- {
- if (linkSpec)
- delete linkSpec;
- if (odLink)
- odLink->Release(ev);
- if (cmd)
- delete cmd;
- FW_THROW_SAME();
- }
- FW_CATCH_END
-
- if (linkSpec)
- delete linkSpec;
-
- return linkDest;
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CLinkManager::PrivMakeLink
- //---------------------------------------------------------------------------------------
- FW_CLinkDestination* FW_CLinkManager::PrivMakeLink(Environment* ev,
- ODLink* odLink,
- ODPasteAsResult& pasteAsResult,
- FW_CPresentation* presentation)
- {
- FW_CLinkDestination* linkDest = NULL;
- FW_VOLATILE(linkDest);
-
- FW_TRY
- {
- ODLinkInfo linkInfo;
- linkInfo.change = kODUnknownUpdate; // not yet updated
- FW_CTime time = FW_CTime::GetCurrentTime();
- linkInfo.creationTime = time.GetTime();
- linkInfo.changeTime = linkInfo.creationTime;
- linkInfo.autoUpdate = pasteAsResult.autoUpdateSetting;
- linkInfo.kind = NULL;
-
- linkDest = this->NewLinkDestination(ev, odLink, &linkInfo, presentation);
- this->AddToDestLinkList(ev, linkDest);
- linkDest->SavePasteAsSettings(ev, pasteAsResult);
-
- linkDest->Register(ev, fPart); // causes LinkUpdated to be called
- if (linkDest->GetUpdateID(ev) != kODUnknownUpdate) // LinkUpdated succeeded
- linkDest->PrivEstablishLink(ev);
- }
- FW_CATCH_BEGIN
- FW_CATCH_EVERYTHING()
- {
- if (linkDest)
- {
- this->RemoveFromDestLinkList(ev, linkDest);
- delete linkDest;
- }
- FW_THROW_SAME();
- }
- FW_CATCH_END
-
- return linkDest;
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CLinkManager::ExternalizeLinks
- //---------------------------------------------------------------------------------------
- void FW_CLinkManager::ExternalizeLinks(Environment* ev, ODStorageUnit* su,
- FW_CCloneInfo* cloneInfo)
- {
- // If we're cloning into a link, OpenDoc will return an invalid ID for each link
- // when we try to clone it. So don't try to clone it.
- if (cloneInfo != NULL && cloneInfo->GetCloneKind(ev) == kODCloneToLink)
- return;
-
- //--- Write out the source links ---
- if (this->CountSourceLinks(ev) > 0)
- {
- //-- Make sure the value is present in the SU --
- FW_SUForceFocus(ev, su, kODPropContents, this->GetSourceLinkFormat(ev));
-
- FW_CLinkMgrLinkSourceIterator iter(this);
- for (FW_CLinkSource* slink = iter.First(); iter.IsNotComplete(); slink = iter.Next())
- {
- slink->ExternalizeLink(ev, su, cloneInfo);
- }
- }
-
- //--- Write out the destination links ---
- if (this->CountDestinationLinks(ev) > 0)
- {
- //-- Make sure the value is present in the SU --
- FW_SUForceFocus(ev, su, kODPropContents, this->GetDestLinkFormat(ev));
-
- FW_CLinkMgrLinkDestIterator iter(this);
- for (FW_CLinkDestination* link = iter.First(); iter.IsNotComplete(); link = iter.Next())
- {
- link->ExternalizeLink(ev, su, cloneInfo);
- }
- }
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CLinkManager::InternalizeLinks
- //---------------------------------------------------------------------------------------
- void FW_CLinkManager::InternalizeLinks(Environment* ev, ODStorageUnit* storageUnit)
- {
- unsigned long valueSize;
-
- if (FW_SUExistsThenFocus(ev, storageUnit, kODPropContents, this->GetSourceLinkFormat(ev)))
- {
- valueSize = storageUnit->GetSize(ev);
- while (storageUnit->GetOffset(ev) < valueSize)
- {
- this->PrivInternalizeOneSourceLink(ev, storageUnit);
- }
- }
-
- if (FW_SUExistsThenFocus(ev, storageUnit, kODPropContents, this->GetDestLinkFormat(ev)))
- {
- valueSize = storageUnit->GetSize(ev);
- while (storageUnit->GetOffset(ev) < valueSize)
- {
- this->PrivInternalizeOneDestLink(ev, storageUnit);
- }
- }
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CLinkManager::PrivInternalizeOneSourceLink
- //---------------------------------------------------------------------------------------
- void FW_CLinkManager::PrivInternalizeOneSourceLink(Environment* ev, ODStorageUnit* storageUnit)
- {
- // Storage unit must be focused to correct property and value (linkSourceFormat)
- ODStorageUnitRef suRef;
- FW_CByteArray byteArray;
- long version;
-
- //--- First check the link version number ---
- storageUnit->GetValue(ev, sizeof(long), byteArray);
- byteArray.CopyBuffer(&version, sizeof(long));
- FW_ASSERT(version == FW_kLinkVersionNumber);
-
- //--- Read the link reference and validate it ---
- storageUnit->GetValue(ev, sizeof(ODStorageUnitRef), byteArray);
- byteArray.CopyBuffer(&suRef, sizeof(ODStorageUnitRef));
- if (storageUnit->IsValidStorageUnitRef(ev, suRef))
- {
- ODID linkID = storageUnit->GetIDFromStorageUnitRef(ev, suRef);
- this->InternalizeSourceLink(ev, linkID, storageUnit);
- }
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CLinkManager::PrivInternalizeOneDestLink
- //---------------------------------------------------------------------------------------
- void FW_CLinkManager::PrivInternalizeOneDestLink(Environment* ev, ODStorageUnit* storageUnit)
- {
- // Storage unit must be focused to correct property and value (linkDestFormat)
- ODStorageUnitRef suRef;
- FW_CByteArray byteArray;
- long version;
-
- //--- First check the link version number ---
- storageUnit->GetValue(ev, sizeof(long), byteArray);
- byteArray.CopyBuffer(&version, sizeof(long));
- FW_ASSERT(version == FW_kLinkVersionNumber);
-
- //--- Read the link reference and validate it ---
- storageUnit->GetValue(ev, sizeof(ODStorageUnitRef), byteArray);
- byteArray.CopyBuffer(&suRef, sizeof(ODStorageUnitRef));
- if (storageUnit->IsValidStorageUnitRef(ev, suRef))
- {
- ODID linkID = storageUnit->GetIDFromStorageUnitRef(ev, suRef);
- this->InternalizeDestLink(ev, linkID, storageUnit);
- }
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CLinkManager::DoInternalizeOneSourceLink
- //---------------------------------------------------------------------------------------
- FW_CLinkSource* FW_CLinkManager::DoInternalizeOneSourceLink(Environment* ev,
- ODStorageUnit* storageUnit,
- ODUpdateID updateID)
- {
- // Override to:
- // - read part-specific link source data from the storageUnit
- // - create and return a link source object
-
- FW_UNUSED(ev);
- FW_UNUSED(storageUnit);
- FW_UNUSED(updateID);
- return NULL;
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CLinkManager::DoInternalizeOneDestLink
- //---------------------------------------------------------------------------------------
- FW_CLinkDestination* FW_CLinkManager::DoInternalizeOneDestLink(Environment* ev, ODStorageUnit* storageUnit,
- ODLink* odLink, ODLinkInfo* linkInfo)
- {
- // Override to:
- // - read part-specific link data from the storageUnit
- // - create and return a link destination object
-
- FW_UNUSED(ev);
- FW_UNUSED(storageUnit);
- FW_UNUSED(odLink);
- FW_UNUSED(linkInfo);
- return NULL;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CLinkManager::RegisterLinks
- //----------------------------------------------------------------------------------------
- void FW_CLinkManager::RegisterLinks(Environment* ev)
- {
- if (this->CountDestinationLinks(ev) > 0)
- {
- FW_CLinkMgrLinkDestIterator iter(this);
- for (FW_CLinkDestination* link = iter.First(); iter.IsNotComplete(); link = iter.Next())
- {
- link->Register(ev, fPart); // auto-update link will have its LinkUpdated method called
- }
- }
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CLinkManager::InternalizeSourceLink
- //----------------------------------------------------------------------------------------
- void FW_CLinkManager::InternalizeSourceLink(Environment* ev, ODID linkID,
- ODStorageUnit* storageUnit)
- {
- // Storage unit must be focused to correct property and value (linkSourceFormat)
- // The linkID must be valid
- ODUpdateID updateID;
- FW_CByteArray byteArray;
- ODDraft* myDraft = fPart->GetDraft(ev);
-
- //-- Read the link source data, using the validated ID
- ODLinkSource* odLinkSource = myDraft->AcquireLinkSource(ev, linkID);
- storageUnit->GetValue(ev, sizeof(ODUpdateID), byteArray);
- byteArray.CopyBuffer(&updateID, sizeof(ODUpdateID));
-
- //-- Read the link source data (part-specific)
- FW_CLinkSource* linkSource = this->DoInternalizeOneSourceLink(ev, storageUnit, updateID);
- if (linkSource)
- {
- //-- Ensure the link source object references our part as the source of the link
- odLinkSource->SetSourcePart(ev, fPart->GetStorageUnit(ev));
-
- linkSource->SetODLinkSource(ev, odLinkSource);
- this->AddToSourceLinkList(ev, linkSource);
- }
-
- odLinkSource->Release(ev); // to balance AcquireLinkSource above
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CLinkManager::InternalizeDestLink
- //----------------------------------------------------------------------------------------
- void FW_CLinkManager::InternalizeDestLink(Environment* ev, ODID linkID,
- ODStorageUnit* storageUnit)
- {
- // Storage unit must be focused to correct property and value (linkDestFormat)
- // The linkID must be valid
- ODLinkInfo linkInfo;
- ODPasteAsResult embedInfo;
- FW_CByteArray byteArray;
- ODDraft* myDraft = fPart->GetDraft(ev);
-
- //-- Acquire the link, using the validated ID
- ODLink* odLink = myDraft->AcquireLink(ev, linkID, NULL);
-
- //--- Read the link info and kind ---
- storageUnit->GetValue(ev, sizeof(ODLinkInfo), byteArray);
- byteArray.CopyBuffer(&linkInfo, sizeof(ODLinkInfo));
- // Allocate space for the kind string (its size is in linkInfo.kind)
- ODType kind = (ODType) FW_CMemoryManager::AllocateBlock((ODULong)linkInfo.kind);
- storageUnit->GetValue(ev, (ODULong)linkInfo.kind, byteArray);
- byteArray.CopyBuffer((void*)kind, (ODULong)linkInfo.kind);
- linkInfo.kind = NULL;
-
- //--- Read the Paste As info, if there is any ---
- FW_Boolean hasEmbedInfo;
- storageUnit->GetValue(ev, sizeof(FW_Boolean), byteArray);
- byteArray.CopyBuffer(&hasEmbedInfo, sizeof(FW_Boolean));
- if (hasEmbedInfo)
- {
- // Read embedInfo struct
- storageUnit->GetValue(ev, sizeof(ODPasteAsResult), byteArray);
- byteArray.CopyBuffer(&embedInfo, sizeof(ODPasteAsResult));
- // Get selectedKind string from link info
- embedInfo.selectedKind = kind;
- // Read translateKind string, if there is one
- if (embedInfo.translateKind != 0)
- {
- kind = (ODType) FW_CMemoryManager::AllocateBlock((ODULong)embedInfo.translateKind);
- storageUnit->GetValue(ev, (ODULong)embedInfo.translateKind, byteArray);
- byteArray.CopyBuffer((void*)kind, (ODULong)embedInfo.translateKind);
- embedInfo.translateKind = kind;
- }
- // Read editor string, if there is one
- if (embedInfo.editor != 0)
- {
- ODEditor temp = (ODEditor) FW_CMemoryManager::AllocateBlock((ODULong)embedInfo.editor);
- storageUnit->GetValue(ev, (ODULong)embedInfo.editor, byteArray);
- byteArray.CopyBuffer((void*)temp, (ODULong)embedInfo.editor);
- embedInfo.editor = temp;
- }
- }
- else // SU contains no embed info; initialize fields in the struct to reflect this
- {
- embedInfo.mergeSetting = kODTrue; // no embedding
- embedInfo.selectedKind = kind;
- embedInfo.translateKind = NULL;
- embedInfo.editor = NULL;
- }
-
- //-- Read the part-specific link data
- FW_CLinkDestination* destLink = this->DoInternalizeOneDestLink(ev, storageUnit, odLink, &linkInfo);
- if (destLink)
- {
- //-- Establish the link
- this->AddToDestLinkList(ev, destLink);
- destLink->SavePasteAsSettings(ev, embedInfo);
- destLink->PrivEstablishLink(ev);
- }
-
- odLink->Release(ev); // to balance AcquireLink above
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CLinkManager::PrivShowLinkSource
- //----------------------------------------------------------------------------------------
- void FW_CLinkManager::PrivShowLinkSource(Environment* ev, FW_CLinkDestination* link)
- {
- FW_Boolean foundSource = true;
- FW_VOLATILE(foundSource);
-
- FW_TRY
- {
- link->GetODLink(ev)->ShowSourceContent(ev);
- }
- FW_CATCH_BEGIN
- FW_CATCH_REFERENCE(FW_XException, ex)
- {
- foundSource = false; // don't re-throw; we'll handle the exception
- }
- FW_CATCH_END
-
- if (!foundSource)
- {
- // If ShowSourceContent throws an exception, display an alert message
- // informing the user that the link-source content could not be shown.
- fPart->PrivShowErrorAlert(ev, FW_kLinkingStrings, FW_kCantFindLinkSourceMsg);
- }
- }
-
- //----------------------------------------------------------------------------------------
- #ifdef FW_BUILD_MAC
-
- static pascal Boolean MacEditInLinkAlertFilter(DialogPtr theDialog,
- EventRecord * theEvent,
- short *itemHit);
-
- #endif
-
- //----------------------------------------------------------------------------------------
- // FW_CLinkManager::PrivShowEditInLinkAlert
- //----------------------------------------------------------------------------------------
- short FW_CLinkManager::PrivShowEditInLinkAlert(Environment* ev)
- {
-
- #ifdef FW_BUILD_MAC
- ModalFilterUPP filterProc = NewModalFilterProc(&MacEditInLinkAlertFilter);
-
- FW_PSharedLibraryResourceFile resFile(ev);
- short item = Alert(FW_kMacEditInLinkDialog, filterProc);
-
- DisposeRoutineDescriptor(filterProc);
- return item;
- #endif
- #ifdef FW_BUILD_WIN
- // Not yet implemented
- #endif
- }
-
- //----------------------------------------------------------------------------------------
- // MacEditInLinkAlertFilter
- //----------------------------------------------------------------------------------------
- #ifdef FW_BUILD_MAC
- static pascal Boolean MacEditInLinkAlertFilter(DialogPtr theDialog,
- EventRecord * theEvent,
- short *itemHit)
- {
- Boolean result = FALSE;
-
- switch (theEvent->what)
- {
- case keyDown:
- case autoKey:
- {
- switch (theEvent->message & charCodeMask)
- {
- case '.':
- if (theEvent->modifiers & cmdKey)
- {
- result = TRUE;
- *itemHit = FW_kCancelEditButtonID;
- }
- break;
-
- case 0x0D:
- case 0x03:
- result = TRUE;
- *itemHit = FW_kFindSourceButtonID;
- break;
-
- case 0x1B:
- result = TRUE;
- *itemHit = FW_kCancelEditButtonID;
- break;
- }
-
- if (result) // flash the button
- {
- long theTick;
- short itemType;
- Handle hItem;
- Rect box;
-
- ::GetDialogItem(theDialog, *itemHit, &itemType, &hItem, &box);
- ::HiliteControl((ControlHandle)hItem, 1);
- ::Delay(6,&theTick);
- ::HiliteControl((ControlHandle)hItem, 0);
- }
- }
- break;
-
- case updateEvt:
- if (theDialog == (DialogPtr)theEvent->message)
- {
- PenState ps;
- Rect box;
- Handle handle;
- short type;
-
- ::SetPort(theDialog);
- ::GetPenState(&ps);
- ::PenSize(3, 3);
- ::GetDialogItem(theDialog, FW_kFindSourceButtonID, &type, &handle, &box);
- ::InsetRect(&box, -4, -4);
- ::FrameRoundRect(&box, 16, 16);
- ::SetPenState(&ps);
- }
- break;
- }
-
- return result;
- }
- #endif
-
- //----------------------------------------------------------------------------------------
- // FW_CLinkManager::GetLinkInfoString
- //----------------------------------------------------------------------------------------
- FW_Boolean FW_CLinkManager::GetLinkInfoString(Environment* ev, FW_CString& infoString)
- {
- // If a link is selected, set infoString to the default Link Info string and return true.
- FW_CLink* selectedLink = this->GetSelectedLink(ev);
- if (selectedLink)
- {
- ::FW_PrivLoadODFString(ev, FW_kLinkInfoString, infoString);
- return true;
- }
-
- return false;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CLinkManager::ShowLinkInfo
- //----------------------------------------------------------------------------------------
- FW_Boolean FW_CLinkManager::ShowLinkInfo(Environment* ev, FW_CFrame* frame)
- {
- // If a link is selected, put up the Link Info dialog, handle it, and return true.
- // Return false if no links are selected.
-
- if (this->CountDestinationLinks(ev) > 0)
- {
- FW_CLinkMgrLinkDestIterator iter(this);
- for (FW_CLinkDestination* link = iter.First(); iter.IsNotComplete(); link = iter.Next())
- {
- if (link->IsLinkSelected(ev))
- {
- link->ShowLinkInfo(ev, frame, this);
- return true;
- }
- }
- }
-
- if (this->CountSourceLinks(ev) > 0)
- {
- FW_CLinkMgrLinkSourceIterator iter(this);
- for (FW_CLinkSource* slink = iter.First(); iter.IsNotComplete(); slink = iter.Next())
- {
- if (slink->IsLinkSelected(ev))
- {
- slink->ShowLinkInfo(ev, frame, this);
- return true;
- }
- }
- }
-
- return false;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CLinkManager::GetSelectedLink
- //----------------------------------------------------------------------------------------
- FW_CLink* FW_CLinkManager::GetSelectedLink(Environment* ev)
- {
- FW_CLinkIterator it(this);
- for (FW_CLink* link = it.FirstLink(); it.IsNotComplete(); link = it.NextLink())
- {
- if (link->IsLinkSelected(ev))
- {
- return link;
- }
- }
- return NULL;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CLinkManager::SelectLink
- //----------------------------------------------------------------------------------------
- void FW_CLinkManager::SelectLink(Environment* ev, FW_CLink* link)
- {
- //--- If a different link is currently selected, de-select it
- FW_CLink* selectedLink = this->GetSelectedLink(ev);
- if (selectedLink && selectedLink != link)
- {
- selectedLink->Select(ev, false);
- selectedLink->InvalidateBorder(ev);
- }
-
- //--- Select the link
- link->Select(ev, true);
- link->InvalidateBorder(ev);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CLinkManager::SetPendingDropLink
- //----------------------------------------------------------------------------------------
- void FW_CLinkManager::PrivSetPendingDropLink(Environment* ev, FW_CLinkSource* linkSource, FW_CFrame* scopeFrame)
- {
- FW_ASSERT(linkSource == NULL || scopeFrame != NULL);
-
- fPendingDropLink = linkSource;
-
- if (linkSource)
- {
- FW_CPrivCreateLinkSourceCommand* cmd = FW_NEW(FW_CPrivCreateLinkSourceCommand, (ev, scopeFrame, this, NULL));
- if (cmd->Execute(ev)) // with a null link, just posts the transaction
- linkSource->PrivSetPendingCommand(ev, cmd);
- }
- }
-
-